package eu.tsp.isensors.test.communication;

import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.lang.Exception;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ResourceIdentifier {

   private final Pattern pattern;
   private final String[] attributeNames;
   private final RequestHandler getHandler;
   private final RequestHandler putHandler;
   private final RequestHandler postHandler;
   private final RequestHandler deleteHandler;

   public ResourceIdentifier(String regex, String[] attributeNames, RequestHandler getHandler, RequestHandler postHandler,
           RequestHandler putHandler, RequestHandler deleteHandler) {
       this.pattern = Pattern.compile(regex);
       this.attributeNames = attributeNames;
       this.getHandler = getHandler;
       this.postHandler = postHandler;
       this.putHandler = putHandler;
       this.deleteHandler = deleteHandler;
   }


   public ResourceIdentifier(String regex, RequestHandler supportsGet) {
       this(regex, new String[] {}, supportsGet, null, null, null);
   }

   public ResourceIdentifier(String regex, String[] attributeNames, RequestHandler supportsGet) {
       this(regex, attributeNames, supportsGet, null, null, null);
   }

   public ResourceIdentifier(String regex, RequestHandler supportsGet, RequestHandler supportsPost) {
       this(regex, new String[] {}, supportsGet, supportsPost, null, null);
   }

   public ResourceIdentifier(String regex, String[] attributeNames, RequestHandler supportsGet, RequestHandler supportsPost) {
       this(regex, attributeNames, supportsGet, supportsPost, null, null);
   }

   public boolean doGet(HttpServletRequest request, HttpServletResponse response)
           throws Exception {

       return doMethod(this.getHandler, request.getPathInfo(), request, response);
   }

   public boolean doPost(HttpServletRequest request, HttpServletResponse response)
           throws Exception {

       return doMethod(postHandler, request.getPathInfo(), request, response);
   }

   public boolean doPut (HttpServletRequest request, HttpServletResponse response)
           throws Exception {

       return doMethod(putHandler, request.getPathInfo(), request, response);
   }

   public boolean doDelete(HttpServletRequest request, HttpServletResponse response)
           throws Exception {

       return doMethod(deleteHandler, request.getPathInfo(), request, response);
   }
 
   /**
    * Test the uri against our pattern. If matched, dispatch to the handler.
    */
   private boolean doMethod(RequestHandler handler, String uri, HttpServletRequest request, HttpServletResponse response) throws Exception {
       if (uri == null){
           uri = "";
       }
       Matcher matcher = pattern.matcher(uri);
       boolean bDid;
       if (matcher.matches()) {
           if (handler == null) {
               response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
               bDid = true;
           } else {
               dispatch(matcher, request, response, handler);
               bDid = true;
           }
       } else {
           bDid = false;
       }
       return bDid;
   }

  
   private void dispatch(Matcher matcher, HttpServletRequest request, HttpServletResponse response,
           RequestHandler listener) throws Exception {

       // The regex matched. Extract all the named attributes from the URL and
       // set them as attributes on the request. Then invoke RequestHandler.
       int n = matcher.groupCount() ;
       if (n != attributeNames.length) {
           throw new RuntimeException("must have same number of matches as attribute names");
       }
        for (int i = 0; i < n; i++) {
            request.setAttribute(attributeNames[i], matcher.group(i + 1));
        }      
        listener.invoke(request, response);
    }
}
